Unity史上最全旋转详解(Rotate,rotation,localEulerAngles,localRotation,万向节锁) 您所在的位置:网站首页 unity 函数参数 Unity史上最全旋转详解(Rotate,rotation,localEulerAngles,localRotation,万向节锁)

Unity史上最全旋转详解(Rotate,rotation,localEulerAngles,localRotation,万向节锁)

2023-12-10 07:53| 来源: 网络整理| 查看: 265

Unity史上最全旋转详解 前言旋转的方法Rotate以及五种重载参数的超级详细理解Rotate(float xAngle, float yAngle, float zAngle);Unity绕轴旋转Rotate(float xAngle, float yAngle, float zAngle, [DefaultValue("Space.Self")] Space relativeTo)Rotate(Vector3 eulers)Rotate(Vector3 eulers, [DefaultValue("Space.Self")] Space relativeTo);Rotate(Vector3 axis, float angle, [DefaultValue("Space.Self")] Space relativeTo); transform的各种旋转相关属性到底是什么rotationlocalRotationeulerAngleslocalEulerAngles 欧拉旋转会导致的万向节锁万向节锁导致的不可解决的问题 怎么使用四元数旋转四元数插值

前言

对于Unity程序员来说,不求甚解是个很好的习惯,我也是个不求甚解的人,但是看了Unity的旋转,有点恶心,老实说,全理解,很难,我也估计没做到,所以我以我现在摸到的东西总结出了一份Unity程序员应该了解的关于Unity旋转相关的知识清单,这个清单避免了四元数和欧拉角转换的原理,还有很多数学证明知识相关,只是想清清楚楚的讲明白对于Unity旋转我们到底应该知道什么,话不多说,上清单

旋转的方法Rotate以及五种重载参数的超级详细理解

UnityAPI讲解是以欧拉角旋转,那么什么是欧拉角,其实就是属性栏我们能看到的三个方向,xyz的值,可以理解为旋转(x,y,z)这就是欧拉角了。那么这个函数怎么用,接着看。 在这里插入图片描述

首先摆出一个旋转和位置参数都是(0,0,0)而且没有父节点的模型出来 在这里插入图片描述 上旋转代码

//求水平输入和垂直输入 float v = Input.GetAxis("Vertical"); float x = Input.GetAxis("Horizontal"); //Time.deltaTime是完成上一帧的时间,Rotate加增量 transform.Rotate(0, x * RotateSpeed * Time.deltaTime, 0);

这里调用 transform.Rotate方法,此方法参数明显是三个float,这里先不具体说,主要讲下Rotate函数是干嘛的,这个函数是给当前物体增加增量,也就是添加旋转,只做一次,所以当我写到Update里面的时候,就是长按就会一直旋转,这里是旋转y轴。现在讲6种重载。

Rotate(float xAngle, float yAngle, float zAngle);

这是最简单的第一种重载,但是却不是我们想象的那么简单,比如Rotate(10,20,30),我们想象的是旋转属性增加增量(10,20,30),结果确实是这样,但是具体实现却不是怎么简单,而是先绕z轴旋转30度,再绕x轴旋转10度,再绕y轴旋转20度,那么怎么叫绕轴旋转,这里加一个知识点,那么知道这个对我们有什么好处呢,后面的一种重载我们就知道了。

Unity绕轴旋转

Unity绕哪个轴旋转就是竖起你的左手,左手四指握紧,大拇指指向轴的方向,四指弯曲方向就是正向旋转了,比如绕y轴20度,就是这个方向。 在这里插入图片描述

Rotate(float xAngle, float yAngle, float zAngle, [DefaultValue(“Space.Self”)] Space relativeTo)

这个重载和上一个重载不一样的地方是多了一个Space参数,就是确定旋转的相对空间,这很重要,带大家看看世界空间和自身空间的区别,加一句,默认是自身空间。 刚才说过旋转绕着轴,现在我们将轴的xyz,想象成实体,就是可以随便移动的,其实世界空间旋转就是轴在,最高父节点身上,自身空间轴在自己身上,现在我们创建一个父物体,给他初始旋转(45,0,0),把人物模型拉到他下面,初始旋转是(0,0,0) 如下 在这里插入图片描述 现在我们来看看世界旋转

transform.Rotate(0, x * RotateSpeed * Time.deltaTime, 0,Space.World);

在这里插入图片描述 然后是自身旋转

transform.Rotate(0, x * RotateSpeed * Time.deltaTime, 0,Space.Self);

在这里插入图片描述 看出我刚才说的轴的感觉了吗,兄弟们。

Rotate(Vector3 eulers)

和第一种一模一样,就是把Rotate(0,0,0)改成了Rotate(new vector(0,0,0))

Rotate(Vector3 eulers, [DefaultValue(“Space.Self”)] Space relativeTo);

和第二种一模一样

Rotate(Vector3 axis, float angle, [DefaultValue(“Space.Self”)] Space relativeTo);

和前面的完全不一样,而且原理也不一样 前面的是哪个轴旋转多少度,前面的只有三个轴,x,y,z,这个重载的Vector可不是旋转的量,而是轴,这个重载让你自己声明轴,然后系统会以axis和(0,0,0)相减的向量为轴,那么转多少度 呢,第二个angle指定要转多少度 angle 要应用的旋转度数。 axis 要应用旋转的轴。 relativeTo 确定在游戏对象本地还是相对于世界空间中的场景来旋转游戏对象。 所以尽量少用,因为轴指定的过于混乱,会得到很不可控的效果。

transform的各种旋转相关属性到底是什么

详细我们第一次旋转的时候,肯定想着和位置一样,直接改变position,却找不到rotation,或者rotation根本不是我们想象的那三个数,我们transform找了一下,发现有这些属性,但是这个根本不是我们属性面板的(0,0,0)哈哈哈,我来缕缕关系。 在这里插入图片描述

rotation

这其实是世界空间下的四元数表示的旋转,其实四元数就是 Quaternion这个类的对象,四元数是一个很复杂的数,但是可以完美表示旋转,但是Unity给我们展示的是欧拉角,也就是三个度数,因为好理解,引擎到头来还是工具,简单是王道,四元数当然是可以和欧拉角也就是我们熟悉的(0,0,0)转换,那么转换肯定很复杂,但是Unity提供了方法,

Quaternion.Euler(yourAngles)

参数就是vector3对象,也就是三元左边就行,就会得到对应的四元数。

localRotation

简单就是本地的四元数了。

eulerAngles

欧拉角,也就是我们熟悉的(0,0,0)了,也就是属性面板上的类型。记得属性面板上的数字永远是本地欧拉角

localEulerAngles

本地旋转欧拉角了

欧拉旋转会导致的万向节锁

那么看起来欧拉角用起来又方便又简单,为啥要有四元数呢,这就谈谈欧拉旋转的问题,但是Unity已经很考虑我们了,基本已经帮我们避免的很了,所以正常使用的时候见不到这个问题的。 刚才也谈了,旋转是先转z,再转x,再转y,x轴的转动90度会使得z轴和y轴共面,产生zy旋转只能在同一平面旋转的结果。 产生了万向节锁之后,就会导致丢失一个旋转分量。但实际上,就算产生了如上的万向节锁,看似不能在绕着原来的世界坐标系的Z轴旋转,但只要调用 Rotate(0,0,z,Space.World),就仍然可以让该物体旋转,并不会让物体无法旋转。

万向节锁导致的不可解决的问题

当你需要做动画的时候,你想从(90,0,0)插值到(150,90,90)的时候,写出了这样的代码

transform.eulerAngles = Vector3.Lerp(transform.eulerAngles, new Vector3(150, 90, 90), 0.5f);

因为y和z会突然跳变,就会形成死锁,甚至卡住电脑。 那为什么这个问题现在还存在呢 因为Unity设置x在中间就是因为一般x不会旋转90度的,常见的旋转插值是对Camera进行的,而如果绕着X轴旋转90度,则意味着正向上,或是正向下,这两种情况都是非常少见的。

怎么使用四元数旋转 transform.rotation = Quaternion.FromToRotation(transform.up, gravityDir) * transform.rotation;

Unity的FromToRotation是一个静态函数,也就是 Quaternion类才能调用的方法,他会返回一个计算后的旋转量,第一个参数是要旋转什么,第二个参数是要旋转到什么方向去这里的三维坐标全是代表一个向量 因为本身的rotation就是四元数,所以我们将要旋转的地方都换算成四元数,赋值给rotation就行了

四元数插值

上面的代码,改成四元数就是

transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.Euler(new Vector3(150,90,90)), dTime);


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

      专题文章
        CopyRight 2018-2019 实验室设备网 版权所有